home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Format Collection 21
/
PC Format CD-ROM Collection 21 (1995-12)(Future Publishing)(GB)[issue 51].iso
/
resource
/
flisumry.poc
< prev
next >
Wrap
Text File
|
1992-08-17
|
15KB
|
453 lines
/*****************************************************************************
* FLISUMRY.POC: Summarize a flic by reducing frames to postage stamp images.
*
* MAINTENANCE:
* 03/01/91 Ian Lepore
* Created.
* 10/15/91 Ian
* Reworked, now uses new PSTAMP.POE and has more features.
* 09/17/92 Ian
* Fixed an off-by-one bug that was being caused by cumulative
* floating point rounding error when adding offset_to_nextframe.
* Now a multiply is used instead of cumulative addition.
****************************************************************************/
#pragma poco library "pstamp.poe"
#include "errcodes.h"
/*----------------------------------------------------------------------------
* the first release of pj/poco didn't include an Err_range error; if
* errcodes.h hasn't defined it, we'll define it here to a similar error.
*--------------------------------------------------------------------------*/
#ifndef Err_range
#define Err_range Err_parameter_range
#endif
/*----------------------------------------------------------------------------
* main menu...
*--------------------------------------------------------------------------*/
char main_curgrid_template[] = "Set Grid (Now %d x %d)";
char main_curgrid_string[4+sizeof(main_curgrid_template)];
char main_menu_title[] = "Summarize Flic Frames:";
char *main_menu[] = {
"Current Flic",
"Flic from Disk",
main_curgrid_string,
"Help",
"Exit",
};
/*----------------------------------------------------------------------------
* grid size menu...
*--------------------------------------------------------------------------*/
char grid_title[] = "Dimension for summary grid:";
char *grid_choices[] = {
"Custom Size",
"2 x 2",
"3 x 3",
"4 x 4",
"5 x 5",
"6 x 6",
"7 x 7",
"8 x 8",
"9 x 9",
"Cancel"
};
/*----------------------------------------------------------------------------
* various "are you sure?" prompts...
*--------------------------------------------------------------------------*/
char replace_flic_prompt[] = "You have %d unsaved changes.\n\n"
"Okay to discard changes and create a "
"new flic containing the summary?"
;
char replace_cel_prompt[] = "Okay to discard current contents of Cel/AnimCel?";
char replace_swap_prompt[] = "Okay to discard current contents of Swap Screen?";
char disk_flicpath_prompt[] = "Please choose flic to summarize:";
/*----------------------------------------------------------------------------
* misc stuff...
*--------------------------------------------------------------------------*/
Boolean is_okay_to_replace_cel = FALSE;
Boolean is_okay_to_replace_swap = FALSE;
char grid_option_gvar[] = "$flisumry_grid_option";
char disk_flicpath_gvar[] = "$flisumry_lastpath";
int grid_dimension; // 3 == 3x3 grid, 4 == 4x4, etc.
void do_help(void)
/*****************************************************************************
* give a little help on what the program is all about.
****************************************************************************/
{
Qtext(
"This program summarizes a flic by creating a screen full of small "
"'postage stamp' images from the flic's frames. It can summarize "
"the flic currently in memory, placing the results in the swap "
"screen, or it can summarize a flic stored on disk, placing the "
"results in the current flic frame."
"\n\n"
"When the current flic is summarized, the resulting summary screen "
"is always the same resolution as the flic itself."
"\n\n"
"When a flic "
"from disk is summarized, it may have different dimensions than the "
"current flic frame. Thus, you can summarize a disk flic onto a "
"frame with a larger resolution, and get larger postage stamps "
"images in the summary."
);
}
void get_grid_choice(Boolean do_dialog)
/*****************************************************************************
* get the user's preference for the postage stamp grid.
* if the do_dialog flag is true, we ask the user via Qmenu(). if the flag
* is false, we retrieve the saved setting from the global variable pool.
* when the user changes the value via the dialog, we store the new value
* into the global variable for next time we're run.
****************************************************************************/
{
int option;
char stored_option[10] = "0";
if (do_dialog) {
option = Qmenu(grid_choices, Array_els(grid_choices), grid_title);
if (option == 1) {
option = grid_dimension;
Qnumber(&option, 2, 25, "Custom X by X grid, select value of X:");
if (option < 2 || option > 25) {
Qerror(Err_range, "Value must be between 2 and 25 inclusive");
return;
}
}
sprintf(stored_option, "%d", option);
GlobalVarSet(grid_option_gvar, stored_option);
} else {
GlobalVarGet(grid_option_gvar, stored_option);
option = atoi(stored_option);
if (option < 2 || option > 25)
option = 4;
}
if (option > 0) {
grid_dimension = option;
sprintf(main_curgrid_string, main_curgrid_template,
grid_dimension, grid_dimension);
}
}
char *ordinal(int num)
/*****************************************************************************
* return the suffix for a number to make the number ordinal.
****************************************************************************/
{
int idx;
static char ordsuffix[10];
static char *suffi[] = {"th","st","nd","rd"};
idx = num % 10;
if ((num > 10 && num < 20) || idx > 3)
idx = 0;
sprintf(ordsuffix,"%d%s", num, suffi[idx]);
return ordsuffix;
}
Errcode summarize_current_flic(void)
/*****************************************************************************
* summarize the current flic into the swap screen.
****************************************************************************/
{
Errcode err;
int dx, dy;
int dw, dh;
int sw, sh;
int linecount;
int num_pstamps;
int curpstamp;
int change_count;
int num_flic_frames;
double offset_to_nextframe;
double curflicframe;
Screen *swapscrn;
Screen *picscrn;
if (SwapExists()) {
if (!is_okay_to_replace_swap) {
if (!Qquestion(replace_swap_prompt))
return Err_abort;
}
}
is_okay_to_replace_swap = TRUE; // only ask once during a run
if (1 >= (num_flic_frames = GetFrameCount())) {
Qtext("Cannot create a summary of a single-frame flic!");
return Err_reported;
}
num_pstamps = grid_dimension * grid_dimension;
if (num_pstamps > num_flic_frames)
num_pstamps = num_flic_frames;
offset_to_nextframe = (double)num_flic_frames / num_pstamps;
if (offset_to_nextframe < 1.0)
offset_to_nextframe = 1.0;
SwapClip(); // make a swap screen
picscrn = GetPicScreen();
swapscrn = GetSwapScreen();
GetScreenSize(picscrn, &dw, &dh);
dw = (dw / grid_dimension) - 1;
dh = (dh / grid_dimension) - 1;
curflicframe = 0.0;
curpstamp = 1;
InitPstampScreen(swapscrn);
for (dy = 0; curpstamp <= num_pstamps; dy += dh) {
for (dx = 0, linecount = 0; linecount < grid_dimension && curpstamp <= num_pstamps; dx += dw, ++linecount) {
SetFrame((int)curflicframe);
printf("Processing frame %d, the %s of %d in the summary",
(int)curflicframe, ordinal(curpstamp), num_pstamps);
MakePstamp(picscrn, swapscrn, dx, dy, dw, dh, TRUE);
++curpstamp;
curflicframe += offset_to_nextframe;
}
}
CleanupPstampScreen(swapscrn);
Qtext("Summary completed successfully, results are in the swap screen.");
unprintf();
return err;
}
int ask_frame_count(int num_cel_frames, int pstamps_per_frame)
/*****************************************************************************
* we have more input frames that will fit in one output frame, ask the user
* how many output frames should appear in the summary.
****************************************************************************/
{
int full_summary_frame_count;
int requested_frame_count;
static char prompt[] = "There are %d input frames. "
"Summarizing all input frames "
"will create %d output frames. "
"If fewer output frames "
"are selected, some input "
"frames will be skipped."
"\n\n"
"Please choose the number of output frames:"
;
char formatted_prompt[15+sizeof(prompt)];
full_summary_frame_count = (num_cel_frames+pstamps_per_frame-1)/pstamps_per_frame;
sprintf(formatted_prompt, prompt, num_cel_frames, full_summary_frame_count);
requested_frame_count = full_summary_frame_count;
if (!Qnumber(&requested_frame_count, 1, full_summary_frame_count, formatted_prompt))
return Err_abort;
if (requested_frame_count > full_summary_frame_count)
return full_summary_frame_count;
else
return requested_frame_count;
}
Errcode summarize_disk_flic(char *flicpath)
/*****************************************************************************
* summarize a flic from disk into the current flic.
****************************************************************************/
{
Errcode err;
int dx, dy;
int dw, dh;
int sw, sh;
int change_count;
int linecount;
int num_output_frames;
int cur_output_frame;
int pstamps_per_frame;
int num_output_pstamps;
int cur_pstamp;
int cur_pstamp_within_frame;
int num_cel_frames;
double cur_cel_frame;
double offset_to_nextframe;
Screen *celscrn;
Screen *picscrn;
/*------------------------------------------------------------------------
* ask permission before wiping out the current flic and/or cel.
*----------------------------------------------------------------------*/
if (0 != (change_count = GetChangeCount())) {
if (!Qquestion(replace_flic_prompt, change_count))
return Err_abort;
}
if (CelExists()) {
if (!is_okay_to_replace_cel) {
if (!Qquestion(replace_cel_prompt))
return Err_abort;
}
}
is_okay_to_replace_cel = TRUE; // only ask permission once
/*------------------------------------------------------------------------
* ask for the input flic/cel name, then load it as an AnimCel.
*----------------------------------------------------------------------*/
if (!Qfile(".FL?;.CEL;.*", "Summarize", flicpath, flicpath, FALSE, disk_flicpath_prompt))
return Err_abort;
if (Success < (err = LoadCel(flicpath))) {
Qerror(err, "Cannot load flic/cel file '%s'", flicpath);
err = Err_reported;
goto CLEANUP_EXIT;
}
if (1 >= (num_cel_frames = CelFrameCount())) {
Qtext("Cannot create a summary of a single-frame flic!");
err = Err_reported;
goto CLEANUP_EXIT;
}
/*------------------------------------------------------------------------
* figure out how many input frames we have, how many postage stamps we
* can put on one output frame, and how many output frames the user wants.
*----------------------------------------------------------------------*/
pstamps_per_frame = grid_dimension * grid_dimension;
cur_output_frame = 0;
if (pstamps_per_frame > num_cel_frames) {
num_output_frames = 1;
num_output_pstamps = num_cel_frames;
} else {
num_output_frames = ask_frame_count(num_cel_frames, pstamps_per_frame);
if (num_output_frames < 1) {
err = Err_abort;
goto CLEANUP_EXIT;
}
num_output_pstamps = num_output_frames * pstamps_per_frame;
if (num_output_pstamps > num_cel_frames)
num_output_pstamps = num_cel_frames;
}
/*------------------------------------------------------------------------
* Set up the postage stamp sizes and placements, init the output frames.
*----------------------------------------------------------------------*/
picscrn = GetPicScreen();
celscrn = GetCelScreen();
SetFrameCount(1); // goto 1st frame, InitPstamp clears it
InitPstampScreen(picscrn); // and lays in the 6-cube color palette.
SetFrameCount(num_output_frames); // now clone the right # of copies of it.
cur_cel_frame = 0.0;
offset_to_nextframe = (double)num_cel_frames / num_output_pstamps;
if (offset_to_nextframe < 1.0)
offset_to_nextframe = 1.0;
GetScreenSize(picscrn, &dw, &dh);
dw = (dw / grid_dimension) - 1;
dh = (dh / grid_dimension) - 1;
/*------------------------------------------------------------------------
* build the summary...
*----------------------------------------------------------------------*/
for (cur_output_frame = 0;
cur_cel_frame < num_cel_frames;
++cur_output_frame) {
InitPstampScreen(picscrn);
for (dy = 0, cur_pstamp_within_frame = 1;
(cur_pstamp_within_frame <= pstamps_per_frame &&
cur_cel_frame < num_cel_frames);
dy += dh) {
for (dx = 0, linecount = 0;
(linecount < grid_dimension &&
cur_pstamp_within_frame <= pstamps_per_frame &&
cur_cel_frame < num_cel_frames);
dx += dw, ++linecount) {
CelSetFrame((int)cur_cel_frame);
printf("Processing frame %d, the %s of %d in the summary",
(int)cur_cel_frame,
ordinal(cur_pstamp), num_output_pstamps);
MakePstamp(celscrn, picscrn, dx, dy, dw, dh, TRUE);
++cur_pstamp_within_frame;
++cur_pstamp;
cur_cel_frame = cur_pstamp * offset_to_nextframe;
}
}
CleanupPstampScreen(picscrn);
NextFrame();
}
CLEANUP_EXIT:
#if __POCO__ < 178 // original Poco version didn't have a CelRelease()
CelGet(0,0,1,1); // function, so we free the bulk of the resources
#else // used by the cel we loaded by cutting out a 1-pixel
CelRelease(); // cel, which hardly uses any resource at all. Later
#endif // versions of Poco have a proper CelRelease().
unprintf();
return err;
}
void main(void)
/*****************************************************************************
* drive main menu dialog, dispatch processing of selections.
****************************************************************************/
{
int option;
static char last_path[PATH_SIZE] = "";
GlobalVarGet(disk_flicpath_gvar,last_path);
get_grid_choice(FALSE); // go load saved grid option from global var
do {
option = Qmenu(main_menu, Array_els(main_menu), main_menu_title);
switch (option) {
case 1:
summarize_current_flic();
break;
case 2:
summarize_disk_flic(last_path);
break;
case 3:
get_grid_choice(TRUE);
break;
case 4:
do_help();
break;
default:
break;
}
} while (option > 0);
GlobalVarSet(disk_flicpath_gvar,last_path);
}